package cn.apelx.shardingjdbc.config;

import org.hibernate.SessionFactory;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.metamodel.spi.MetamodelImplementor;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.SingleTableEntityPersister;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 实体Util
 *
 * @author apelx
 * @since 2022-05-14
 */
@Component
public class EntityBeanUtil implements InitializingBean {

    private static Map<Class<?>, SingleTableEntityPersister> map = new ConcurrentHashMap<>(16);
    @Autowired
    private EntityManager entityManager;

    @Override
    public void afterPropertiesSet() throws Exception {
        EntityManagerFactory entityManagerFactory = entityManager.getEntityManagerFactory();
        SessionFactoryImpl sessionFactory = (SessionFactoryImpl) entityManagerFactory.unwrap(SessionFactory.class);
        MetamodelImplementor metamodel = sessionFactory.getMetamodel();
        Map<String, EntityPersister> entityPersisterMap = metamodel.entityPersisters();

        Set<Map.Entry<String, EntityPersister>> entries = entityPersisterMap.entrySet();

        for (Map.Entry<String, EntityPersister> entry : entries) {
            // 全限定类名
            String className = entry.getKey();
            SingleTableEntityPersister entityPersister = (SingleTableEntityPersister) entry.getValue();
            // 表名
            String tableName = entityPersister.getTableName();

            map.put(Class.forName(className), entityPersister);
        }
    }

    public static Map<Class<?>, SingleTableEntityPersister> getEntityMap() {
        return map;
    }

    public static Set<String> getAllTableNames() {
        return map.values().stream().map(SingleTableEntityPersister::getTableName).collect(Collectors.toSet());
    }

}
